﻿#ifndef ROTEST_H
#define ROTEST_H

#include "remoteobject.h"

/*
一个远程对象的设计需要满足以下前提
1.继承RemoteObject类
2.类上有REFLECTABLE宏

一个远程对象类可具备以下三类成员
1.信号
2.槽
3.属性

每种成员都需要在类定义中声明，在类实现中注册元信息

信号：
信号是一种仅能够从原件影响到副本的成员，使用RO_DECL_PROPERTY声明，RO_META_SIGNAL注册。
当原件的信号被激活后，它会通过网络传递到每个副本，使得副本的相同信号被激活
但是副本的信号被激活不会影响到原件，也不会影响到其它副本

槽：
槽是一种仅能够从副本影响到原件的成员，使用RO_DECL_FUNCTION_1_R声明 RO_META_FUNCTION注册，其中声明函数中的数字代表该槽有几个参数，后缀R代表该槽函数是否有返回值
当声明一个槽函数后，它会自动产生三个成员函数，分别是（假如槽函数名称为Print,参数是int）Print（int value）;PrintImp(int value);PrintAsync(int value)
Print（int value）;是槽函数的外部调用接口。可以用反射调用。
PrintImp(int value);是槽函数的内部实现。需要用户实现其内部逻辑。可以反射调用
PrintAsync（int value）；是槽函数的同步调用接口。不可以反射调用。

当副本调用了槽函数时，它会将槽的id以及参数发送给原件，交由原件执行函数实现。
如果槽函数没有返回值的话，则默认为异步调用，直接返回。
如果槽函数有返回值的话，则默认为同步调用，等待原件槽函数执行完毕将返回值传递回来后才执行下一步。

当原件调用了槽函数时，它会直接调用函数实现。


属性：
属性是一种能够被原件和副本相互影响的成员，使用RO_DECL_PROPERTY声明，RO_META_PROPERTY注册

当使用RO_DECL_PROPERTY声明后会自动产生5个成员，分别是GetXXX;SetXXX;XXXChanged;GetXXXImp;SetXXXImp
GetXXX;SetXXX;为属性访问的外部接口
GetXXXImp;SetXXXImp为属性访问的内部实现
XXXChanged为属性改变的信号，需要开发者在SetXXXImp中调用

当原件修改某个属性时，它会将改变后的值分发给每个副本。
当副本修改某个属性时，它会将属性的id和值发给原件，由原件修改，然后再通知给每个副本。
*/

class PT
{
public:
	PT() {

	}

	PT(const PT& o) {
		std::cout << "Copy" << std::endl;
	}

	bool operator == (const PT& o) {
		return true;
	}

	int i;
};

DECL_VARIANT_TYPE(PT)



class ROTest:public RemoteObject
{
public:
    REFLECTABLE(ROTest,RemoteObject)
    ROTest();

	ROTest(int,double);

    //声明属性
    RO_DECL_PROPERTY(int,Number);

    //声明函数
    RO_DECL_FUNCTION_1_R(Print,int,Variant,number);

    //声明信号
    RO_DECL_SIGNAL(Clicked,int,double);

	//声明属性
	RO_DECL_PROPERTY_SIMPLE(std::string, Name);


	RO_DECL_FUNCTION_3_R(Print2,int, Variant, number,int,name,double,r);

	void PR(const PT& pt) {
		std::cout << 123 << std::endl;
	}

	void Say() {
		std::cout << 123 << std::endl;
	}

	static void SetID(double id) {
		m_id = id;
	}

	static double GetID() {
		return m_id;
	}

private:
    int Number;
	std::string Name;
	static double m_id;
};

#endif // ROTEST_H


